
#include "PConfigDB.h"

int PConfigTable::open(const pstring &describe)
{
	clear();

	int index = 0;
	pstring pt=describe.getRange(index, '\t');
	if (pt.length() == 0) return -1;
	table_name = pt;
	pt=describe.getRange(index, '\t');
	if (pt.length() == 0) return -1;
	file_name = pt;
	
	int index0 = index;
	_columns = 0;
	while (true)
	{
		pt = describe.getRange(index0, '\t');
		if (pt.length() == 0) break;
		++_columns;
	}
	pfield = new pstring[_columns];
	ptype = new pstring[_columns];

	int num = 0;
	while (true)
	{
		pt = describe.getRange(index, '\t');
		if (pt.length() == 0) break;
		int i=0;
		pfield[num] = pt.getRange(i, ',');
		ptype[num] = pt.getRange(i, ',');
		++num;
	}

	FILE* in=0;
	if (_wfopen_s(&in, file_name, L"rb") == 0)
	{
		pt.reset();
		int ch = 0;
		while ((ch = fgetwc(in)) != WEOF)
		{
			if (ch == '\n')
			{
				pt.removeBack('\r', 0);
				int i = 0;
				int cols = 0;
				pstring* pr = new pstring[_columns];
				while (i < pt.length() && cols < _columns) pr[cols++] = pt.getRange(i, '\t');
				_insert(pr);
				pt.reset();
			}
			else pt.append(ch);
		}
		fclose(in);
	}
	return 0;
}

void PConfigTable::close()
{
	save();
	clear();
}

bool PConfigTable::save()
{
	if (_flag)
	{
		FILE *out;
		wchar_t t = 0xFEFF;
		if (_wfopen_s(&out,file_name, L"wb")==0)
		{
			pstring pt;
			fwrite(&t, 2, 1, out);
			for (int i = 0; i < _rows; ++i)
			{
				pt.reset();
				for (int j = 0; j < _columns; ++j)
				{
					pt += precord[i][j];
					pt += '\t';
				}
				pt.last()= '\n';
				fwrite(pt, sizeof(wchar_t),pt.length(),out);
			}
			fclose(out);
			_flag = 0;
			return true;
		}
		return false;
	}
	else return true;
}

void PConfigTable::_insert(pstring *record)
{
	if (_rows >= _capacity)
	{
		_capacity *= 2;
		pstring ** ptemp = new pstring *[_capacity];
		for (int i = 0; i < _capacity; ++i) ptemp[i] = 0;
		for (int i = 0; i < _rows; ++i) ptemp[i] = precord[i];
		delete[] precord;
		precord = ptemp;
	}
	precord[_rows++] = record;
}

void PConfigTable::insert(const pstring *record)
{
	pstring * p = new pstring[_columns];
	for (int i = 0; i < _columns; ++i) p[i] = record[i];
	_insert(p);
	++_flag;
}

bool PConfigTable::update(const PQueryItem& _query, const PQueryItem& _update)
{
	bool t = false;
	for (int i = 0; i < _rows; ++i)
	{
		if (_query.compare(precord[i]))
		{
			_update.put(precord[i]);
			++_flag;
			t = true;
		}
	}
	return t;
}

PConfigRecords PConfigTable::query() const
{
	PConfigRecords prds;
	for (int i = 0; i < _rows; ++i)
	{
		prds.append(precord[i]);
	}
	return prds;
}

PConfigRecords PConfigTable::query(const PQueryItem& item) const
{
	PConfigRecords prds;
	for (int i = 0; i < _rows; ++i)
	{
		if (item.compare(precord[i])) prds.append(precord[i]);
	}
	return prds;
}

void PConfigTable::remove(const PQueryItem& item)
{
	for (int i = 0; i < _rows; ++i)
	{
		if (item.compare(precord[i]))
		{
			delete[] precord[i];
			precord[i] = 0;
		}
	}
	for (int i = _rows - 1; i >= 0; --i)
	{
		if (precord[i] == 0)
		{
			for (int j = i; j < _rows - 1; ++j) precord[j] = precord[j + 1];
			--_rows;
		}
	}
}
void PConfigTable::clear()
{
	for (int i = 0; i < _capacity; ++i)
	{
		if (precord[i]) delete[] precord[i];
		precord[i] = 0;
	}
	if(pfield) delete[] pfield;
	pfield = 0;
	if (ptype) delete[] ptype;
	ptype = 0;

	table_name.reset();
	file_name.reset();

	_rows = 0;
	_columns = 0;
	_flag = 0;
}
void PConfigTable::remove()
{
	for (int i = 0; i < _rows; ++i)
	{
		delete[] precord[i];
		precord[i] = 0;
		++_flag;
	}
	_rows = 0;
}

int PConfigDB::open(const wchar_t* file)
{
	pstring pt,ps;
	if (!ps.fromFile(file)) return -2;
	int index = 1;
	while (true)
	{
		pt = ps.getRange(index, '\n');
		if (pt.length() == 0) break;
		PConfigTable *ptab = new PConfigTable;
		int ret = 0;
		if ((ret = ptab->open(pt)) < 0)
		{
			delete ptab;
			return ret;
		}
		insertTable(ptab);
	}
	return true;
}

int PConfigDB::open(const char* file)
{
	pstring pt, ps;
	if (!ps.fromFile(file)) return -2;
	int index = 1;
	while (true)
	{
		pt = ps.getRange(index, '\n');
		if (pt.length() == 0) break;
		PConfigTable* ptab = new PConfigTable;
		int ret = 0;
		if ((ret = ptab->open(pt)) < 0)
		{
			delete ptab;
			return ret;
		}
		insertTable(ptab);
	}
	return 0;
}

void PConfigDB::close()
{
	for (int i = 0; i < _count; ++i)
	{
		ptable[i]->close();
	}
}

void PConfigDB::insertTable(PConfigTable *ptab)
{
	if (_count >= _capacity)
	{
		int cap = _capacity * 2;
		PConfigTable **ptemp = new PConfigTable*[cap];
		for (int i = 0; i < cap; ++i) ptemp[i] = 0;
		for (int i = 0; i < _capacity; ++i) ptemp[i] = ptable[i];
		delete[] ptable;
		ptable = ptemp;
		_capacity = cap;
	}
	ptable[_count++] = ptab;
}

PConfigTable * PConfigDB::getTable(const pstring &name)
{
	for (int i = 0; i < _count; ++i)
	{
		if (ptable[i]->table_name == name) return ptable[i];
	}
	return 0;
}
